package com.dataart.training.crimequalification.beans;

import com.dataart.training.crimequalification.facesutils.FacesMessageHandlingUtils;
import com.dataart.training.crimequalification.service.AuthenticationService;
import com.dataart.training.crimequalification.service.AuthenticationServiceImpl;
import com.dataart.training.crimequalification.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.Date;

/**
 * JSF managed bean responsible for handling authentication-related tasks.
 */

@ManagedBean
@Component
@Scope("session")
public class LoginBean implements Serializable {

    //----------------------------------------------------------------------

    @SuppressWarnings("unused")
    static final long serialVersionUID = 42L;

    //----------------------------------------------------------------------

    private static final Logger logger = LoggerFactory
            .getLogger(LoginBean.class);

    //----------------------------------------------------------------------

    private String username;
    private String password;

    private String loginResult;

    private boolean loggedIn;

    // ----------------------------------------------------------------------

    @Autowired
    @Qualifier(value = "customAuthenticationManager")
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserService userService;

    // ----------------------------------------------------------------------

    public void performAuthenticationCheck() {

        AuthenticationService authUtils = new AuthenticationServiceImpl();
        this.loggedIn = authUtils.isAuthenticationPerformed();
    }

    //-------------------------------------------------------------

    @PostConstruct
    private void init() {

        logger.debug("Login bean created at " + new Date());

        performAuthenticationCheck();

        if (loggedIn) {
            loginResult = "successfulLogin";
        } else {
            loginResult = "notLoggedIn";
        }
    }

    //-------------------------------------------------------------


    public void initiateLogin() {
        loginResult = "loginInitiated";
    }

    public String doLogin() {

        AuthenticationService authUtils = new AuthenticationServiceImpl();

        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();

        this.loggedIn = authUtils.doProgrammaticLogin(request, authenticationManager, username, password);

        if (!loggedIn) {

            FacesMessageHandlingUtils facesMessageHandlingUtils = new FacesMessageHandlingUtils();
            facesMessageHandlingUtils.addMessageToComponent("loginForm",
                    "The username or password you have entered is incorrect.");
            loginResult = "failedLogin";
            return null;

        } else {
            loginResult = "successfulLogin";
        }

        return "/views/index?faces-redirect=true";
    }

    public String doLogout() {

        loginResult = "loggedOut";

        HttpServletRequest request
                = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();

        HttpServletResponse response
                = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();

        AuthenticationService authUtils = new AuthenticationServiceImpl();

        try {
            authUtils.doProgrammaticLogout(request, response);
        } catch (Exception e) {

            FacesContext.getCurrentInstance()
                    .getExternalContext().getSessionMap().put(ErrorBean.ERROR_MESSAGE_KEY,
                    "Failed to log out due to internal server error, please try again later.");
            return "/views/errorpage?faces-redirect=true";
        }

        loggedIn = false;

        return "/views/index?faces-redirect=true";

    }

    // --------------------------------------------------------------------

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public boolean getLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getLoginResult() {
        return loginResult;
    }

    public void setLoginResult(String loginResult) {
        this.loginResult = loginResult;
    }

}